package com.puzzlebazar.client.hashiwokakero;

import com.puzzlebazar.client.util.Vec2i;

public class Island {

	private final Vec2i loc;
	private int value;
	private Bridge bridges[] = new Bridge[4];
	
	/**
	 * Creates a new Hashiwokakero island having the given value
	 * 
	 * @param loc The location of the island
	 * @param value The value for the island (the number of connected bridges)
	 */
	public Island(Vec2i loc, int value) {
		this.loc = loc;
		this.value = value;
	}

	/**
	 * @return The value for this island
	 */
	public int getValue() {
		return value;
	}

	/**
	 * Access a bridge in a specified direction from an island
	 * 
	 * @param direction  The direction from which to get a bridge (NORTH, EAST, SOUTH, WEST) 
	 * @return The bridge in the specified direction
	 * @throws Exception
	 */
	public Bridge getBridge(int direction) throws Exception {
		checkDirection(direction);
		return bridges[direction];
	}
		
	/**
	 * Connect the island to a bridge in the specified direction. User must make sure there is
	 * no bridge in this direction, potentially by calling removeBridge.
	 * 
	 * @param direction  The direction in which to add a bridge (NORTH, EAST, SOUTH, WEST) 
	 * @throws Exception
	 */
	public void connectToBridge(int direction, Bridge bridge) throws Exception {
		if( bridge == null ) throw new Exception( "Connecting to null bridge (use disconnectFromBridge instead)" );
		checkDirection(direction);
		if( bridges[direction] != null ) throw new Exception( "Bridge already present, cannot connect" );
		bridge.connectTo( this );		
		bridges[direction] = bridge;
	}

	/**
	 * Disconnect the island from the bridge in the specified direction. 
	 * 
	 * @param direction  The direction in from which to disconnect a bridge (NORTH, EAST, SOUTH, WEST) 
	 * @throws Exception
	 */
	public void disconnectFromBridge(int direction) throws Exception {
		checkDirection(direction);
		if( bridges[direction] == null ) throw new Exception( "No bridge to disconnect" );
		disconnectFromBridgeNoCheck( direction );
	}
	

	/**
	 * Disconnect the island from the specified bridge. 
	 * 
	 * @param bridge The bridge to disconnect
	 * @throws Exception
	 */
	public void disconnectFromBridge(Bridge bridge) throws Exception {
		if( bridge == null ) throw new Exception( "Disconnecting from a null bridge" );
		int direction = 0;
		while( direction < 4 ) {
			if( bridges[direction] == bridge ) {
				disconnectFromBridgeNoCheck(direction);
				return;
			}			
			++direction;
		}
		throw new Exception( "Bridge not found, cannot disconnect." );
	}
	
	/**
	 * Same as disconnectFromBridge, but does not perform explicit checks
	 * 
	 * @param direction The direction in from which to disconnect a bridge (NORTH, EAST, SOUTH, WEST) 
	 */
	private void disconnectFromBridgeNoCheck(int direction) throws Exception {
		bridges[direction].disconnectFrom( this );
		bridges[direction] = null;		
	}

	/**
	 * Checks if a direction is valid, throws an exception if not
	 * 
	 * @param direction Direction to check
	 * @throws Exception
	 */
	private void checkDirection(int direction) throws Exception {
		if( direction < 0 || direction >= 4 ) throw new Exception ( "Invalid direction" );
	}


	/**
	 * @return The location of this island
	 */
	public Vec2i getLoc() {
		return loc;
	}
	
	
}
